﻿using System;
using System.ServiceModel;
using System.Diagnostics;
using System.IO;

namespace AsianOptionsService
{

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class Service1 : IService1
    {
        

        public double ComputeOption(int typeId, int dayNum, double interest, double initial, double exercise, double up, double down, double deltaT, 
            double threshold, bool isCall, bool isFixed, bool isUp, int isAverage,int otherChoice, double var, int brownApproxiMethod, int runs, int periods, int clientId)
         {
            BasedOptions op = null;


            switch(typeId)
            {
                case 1:
                    op = new AsianOption(typeId,  dayNum,  interest,  initial,  exercise,  up,  down,  deltaT,  threshold,  isCall,  isFixed, isUp, isAverage, otherChoice,  var,  brownApproxiMethod);
                    break;
                case 2:
                    op = new KnockInOutOption(typeId,  dayNum,  interest,  initial,  exercise,  up,  down,  deltaT,  threshold,  isCall,  isFixed, isUp, isAverage, otherChoice,  var,  brownApproxiMethod);
                    break;
                case 3:
                    op = new LookBackOption(typeId,  dayNum,  interest,  initial,  exercise,  up,  down,  deltaT,  threshold,  isCall,  isFixed, isUp, isAverage, otherChoice,  var,  brownApproxiMethod);
                    break;
     
            }
            if (op == null)
                return -1;
            else
                return op.compute_price(runs, periods, clientId);
         }


        static void Log(string msg, int clientId)
        {
            File.AppendAllText(@"\\viewnode\SSC\HPC140\" + Environment.GetEnvironmentVariable("CCP_JOBID") + "_" + clientId + "_output.txt", msg);
        }
        static double gaussDistribution(Random rand)
        {
            double sum = 0;
            for (int i = 0; i < 12; i++)
                sum += rand.NextDouble();
            return sum - 6.0;
        }
        static double nextPrice(double curPrice, Random rand, double sigma, double interest, double deltaT)
        {
            return Math.Exp(deltaT * (interest - 0.5 * Math.Pow(sigma, 2)) + sigma * Math.Pow(deltaT, 0.5) * gaussDistribution(rand));
        }
        public double ArithmeticAverageAsianOptions(int brownApproxiMethod, double initial, double exercise, double sigma, double up, double down, double interest, int periods, double deltaT, int runs, string callPut, string fixedFloating, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;

            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                double sumPricePath = initial;
                if (brownApproxiMethod == 0)
                    for (int i = 1; i <= periods; i++)
                    {
                        pricePath[0] = initial;
                        double rn = rand.NextDouble();

                        if (rn > pidown)
                        {
                            pricePath[i] = pricePath[i - 1] * up;
                        }
                        else
                        {
                            pricePath[i] = pricePath[i - 1] * down;
                        }
                        sumPricePath += pricePath[i];
                    }
                else if (brownApproxiMethod == 1)
                    for (int i = 1; i <= periods; i++)
                    {
                        pricePath[0] = initial;
                        pricePath[i] = nextPrice(pricePath[i - 1], rand, sigma, interest, deltaT);
                        sumPricePath += pricePath[i];
                    }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }
                priceAverage = sumPricePath / (periods + 1);
                if (fixedFloating.Equals("fixed"))
                {
                    if (callPut.Equals("call"))
                        callPayOff = Math.Max(priceAverage - exercise, 0);
                    else if (callPut.Equals("put"))
                        callPayOff = Math.Max(exercise - priceAverage, 0);
                }
                else if (fixedFloating.Equals("floating"))
                {
                    if (callPut.Equals("call"))
                        callPayOff = Math.Max(priceAverage - pricePath[periods], 0);
                    else if (callPut.Equals("put"))
                        callPayOff = Math.Max(pricePath[periods] - priceAverage, 0);
                }

                temp += callPayOff;

                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);


            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double GeometricAverageAsianOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, string callPut, string fixedFloating, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;

            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                double sumPricePath = Math.Log(initial);

                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    sumPricePath += Math.Log(pricePath[i]);
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }

                priceAverage = Math.Exp(sumPricePath / (periods + 1));
                if (fixedFloating.Equals("fixed"))
                {
                    if (callPut.Equals("call"))
                        callPayOff = Math.Max(priceAverage - exercise, 0);
                    else if (callPut.Equals("put"))
                        callPayOff = Math.Max(exercise - priceAverage, 0);
                }
                else if (fixedFloating.Equals("floating"))
                {
                    if (callPut.Equals("call"))
                        callPayOff = Math.Max(priceAverage - pricePath[periods], 0);
                    else if (callPut.Equals("put"))
                        callPayOff = Math.Max(pricePath[periods] - priceAverage, 0);
                }

                temp += callPayOff;

                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);

            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double KnockInUpOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, double threshold, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random();
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                bool flag = false;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] > threshold)
                    {
                        flag = true;
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }
                if (flag)
                {
                    callPayOff = Math.Max(pricePath[periods] - exercise, 0);
                }
                else
                {
                    callPayOff = 0;
                }
                //priceAverage = sumPricePath / (periods + 1);


                temp += callPayOff;

                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        //看跌敲出期权
        public double KnockOutDownOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, double threshold, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                bool flag = false;
                int lastIndex = periods;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] > threshold)
                    {
                        flag = true;
                        lastIndex = i;
                        break;
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= lastIndex; i++)
                        if (i != lastIndex)
                            Log(pricePath[i] + "->", clientId);
                        else
                        {
                            if (lastIndex != periods)
                                Log("option is koncked out!\r\n\r\n", clientId);
                            else
                                Log(pricePath[i] + "\r\n\r\n", clientId);
                        }
                }
                if (!flag)
                {
                    callPayOff = Math.Max(exercise - pricePath[periods], 0);
                }
                else
                {
                    callPayOff = 0;
                }
                //priceAverage = sumPricePath / (periods + 1);


                temp += callPayOff;

                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double KnockInDownOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, double threshold, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                bool flag = false;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] < threshold)
                    {
                        flag = true;
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }
                if (flag)
                {
                    //callPayOff = Math.Max(exercise - pricePath[periods], 0);
                    callPayOff = Math.Max(pricePath[periods] - exercise, 0);
                }
                else
                {
                    callPayOff = 0;
                }
                //priceAverage = sumPricePath / (periods + 1);


                temp += callPayOff;
                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);

            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        //看涨敲出期权
        public double KnockOutUpOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, double threshold, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;



            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                bool flag = false;
                int lastIndex = periods;
                double sumPricePath = initial;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] < threshold)
                    {
                        flag = true;
                        lastIndex = i;
                        break;
                    }
                    sumPricePath += pricePath[i];
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= lastIndex; i++)
                        if (i != lastIndex)
                            Log(pricePath[i] + "->", clientId);
                        else
                        {
                            if (lastIndex != periods)
                                Log("option is koncked out!\r\n\r\n", clientId);
                            else
                                Log(pricePath[i] + "\r\n\r\n", clientId);
                        }
                }
                if (!flag)
                {
                    callPayOff = Math.Max(sumPricePath / (periods + 1) - exercise, 0);
                    //callPayOff = Math.Max(pricePath[periods] - exercise, 0);
                }
                else
                {
                    callPayOff = 0;
                }
                //priceAverage = sumPricePath / (periods + 1);


                temp += callPayOff;
                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0:0.000} stdErr :{1:0.000}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double FixedLookBackUpOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                double maxPrice = initial;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] > maxPrice)
                    {
                        maxPrice = pricePath[i];
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }
                callPayOff = Math.Max(maxPrice - exercise, 0);

                temp += callPayOff;
                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double FloatLookBackUpOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                double maxPrice = initial;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] > maxPrice)
                    {
                        maxPrice = pricePath[i];
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }
                callPayOff = maxPrice - pricePath[periods];

                temp += callPayOff;
                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double FixedLookBackDownOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                double minPrice = initial;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] < minPrice)
                    {
                        minPrice = pricePath[i];
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }

                callPayOff = Math.Max(exercise - minPrice, 0);

                temp += callPayOff;
                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }

        public double FloatLookBackDownOptions(double initial, double exercise, double up, double down, double interest, int periods, int runs, int clientId)
        {
            double[] pricePath = new double[periods + 1];

            // Risk-neutral probabilities
            double piup = (interest - down) / (up - down);
            double pidown = 1 - piup;

            double temp = 0.0;

            Random rand = new Random(clientId * 100);
            //double priceAverage = 0.0;
            double callPayOff = 0.0;
            double sumPayOff = 0.0;
            double sumSquarePayOff = 0.0;


            for (int index = 0; index < runs; index++)
            {
                // Generate Path
                double minPrice = initial;
                for (int i = 1; i <= periods; i++)
                {
                    pricePath[0] = initial;
                    double rn = rand.NextDouble();

                    if (rn > pidown)
                    {
                        pricePath[i] = pricePath[i - 1] * up;
                    }
                    else
                    {
                        pricePath[i] = pricePath[i - 1] * down;
                    }
                    if (pricePath[i] < minPrice)
                    {
                        minPrice = pricePath[i];
                    }
                }
                if (index % 10000 == 0)
                {
                    Log("pathId:" + (clientId * 5000000 / 32 + index / 10000) + "\r\n", clientId);
                    for (int i = 0; i <= periods; i++)
                        if (i != periods)
                            Log(pricePath[i] + "->", clientId);
                        else
                            Log(pricePath[i] + "\r\n\r\n", clientId);
                }

                callPayOff = pricePath[periods] - minPrice;

                temp += callPayOff;
                sumPayOff += callPayOff / Math.Pow(interest, periods);
                sumSquarePayOff += callPayOff * callPayOff / Math.Pow(interest, 2 * periods);
            }
            double stdDev = Math.Sqrt(sumSquarePayOff - sumPayOff * sumPayOff / runs) / ((runs == 1) ? 1 : runs - 1);
            double stdErr = stdDev / Math.Sqrt(runs);
            Log(string.Format("stdDev :{0} stdErr :{1}\r\n", stdDev, stdErr), clientId);
            double returnValue = (temp / Math.Pow(interest, periods)) / runs;
            return returnValue;
        }
    }

}
